import pandas as pd
import numpy as np
import math

#飞机时刻表数据集与尾流安全距离数据集
Timetable = pd.read_csv("F:/plane_information/timetable.csv" , nrows = 10 , usecols = [0 , 1 , 2 , 3 , 4])   # 改nrows的个数为需要的飞机个数
Safety_distance = pd.read_csv("F:/plane_information/Safety_distance.csv" , nrows = 4 , usecols = [0 , 1 , 2 , 3])

class Env:
    def __init__(self):
        self.action_space = ["FCFS" , "SJF"]
        self.n_actions = len(self.action_space)
        self.Timetable = Timetable

    #航班的初始化,最开始的时候无飞机
    def reset(self):
        observation = 0
        nowTime = 0
        Timetable.loc[0:, 2:4] = 0
        return observation , nowTime


    #环境的更新
    def update_env(self ,plane_num , nowTime):
        buffer_list = []    # 初始化缓冲队列

        #1.通过当前的时间，拿到当前nowtime的缓冲队列,同时去掉已经离港的航班
        TN =  0 # TN代表被延后航班的个数
        for i in range(plane_num):
            if nowTime >= Timetable.loc[i]["etd"] and Timetable.loc[i]["leave"] == 0:

                buffer_list.append(i)
                if nowTime - Timetable.loc[i]["etd"] > 30:
                    TN += 1

        #3.计算当前对应的状态
        N = len(buffer_list)    # N代表 nowTime 时刻下缓冲队列中航班的个数
        observation = self.find_ob(TN , N)   #根据 TN 和 N，得到当前所处的状态

        return observation , buffer_list

    #根据TN与N的值计算当前对应的状态
    def find_ob(self , TN , N):
        if N == 0:
            observation = 0
        elif N == 1:
            observation = 1
        else:
            t_ob = math.ceil(TN / N * 100)
            if t_ob >= 0 and t_ob <= 20:
                observation = 2
            elif t_ob > 20 and t_ob <= 40:
                observation = 3
            elif t_ob > 40 and t_ob <= 60:
                observation = 4
            elif t_ob > 60 and t_ob <= 80:
                observation = 5
            elif t_ob > 80 and t_ob <= 100:
                observation = 6
        return observation

    #奖励值判断：延误的时间 / 根据航班的大小(即实际影响时间)来一次给出航班的奖励值
    def get_reward(self , first_plane):
        W = Timetable.loc[first_plane , "atd"] - Timetable.loc[first_plane , "etd"]
        reward = -1 * math.ceil(W / Safety_distance.loc[Timetable.loc[first_plane]["Size"]][3])
        return reward

    #环境奖励值设计
    def step(self , observation , a , buffer_list , NowTime):
        #1.下一个动作,按照动作选出符合标准的下一个航班,并更新当前离港的飞机的时间
        if a == 0:
            first_plane = buffer_list[0]
        else:
            #找到当前缓冲队列中的最小的飞机
            min_size = 3
            first_plane = 0
            for i in range(len(buffer_list)):
                if Timetable.loc[buffer_list[i] , "Size"] < min_size:
                    min_size = Timetable.loc[buffer_list[i] , "Size"]
                    first_plane = buffer_list[i]
        #print(Timetable , first_plane)
        Timetable.loc[first_plane, "atd"] = NowTime

        #2.根据航班的大小，计算当前航班对后序航班无影响之后的时间，并标记当前飞机已经离港
        NowTime += Safety_distance.loc[Timetable.loc[first_plane]["Size"]][3]
        Timetable.loc[first_plane , "leave"] = 1

        #3.根据当前的航班动作，计算出下一个动作的状态
        next_s ,  next_list = self.update_env(10 , NowTime)
        #4.奖励值
        reward = self.get_reward(first_plane)
        #print(buffer_list , first_plane)
        return next_s , reward , next_list , NowTime , first_plane

    #对当前序列进行计算
    def carculate_dtime(self , plane_list):
        sum_dtime = 0
        for i in range(len(plane_list)):
            sum_dtime += Timetable.loc[plane_list[i] , "atd"] - Timetable.loc[plane_list[i] , "etd"]
        return sum_dtime

    #针对FCFS策略的计算
    def calculate_fcfs_dtime(self , plane_num , iteration_num):
        sum_dtime = 0
        fcfs_record = []

        for i in range(plane_num):
            # 1.对航班atd的计算
            if i == 0:
                Timetable.loc[i]["atd"] = Timetable.loc[i]["etd"]
            else:
                Timetable.loc[i]["atd"] = Timetable.loc[i - 1]["atd"] + Safety_distance.loc[Timetable.loc[i - 1]["Size"]][3]

            # 2.为了防止提前起飞
            if Timetable.loc[i]["atd"] < Timetable.loc[i]["etd"]:
                Timetable.loc[i]["atd"] = Timetable.loc[i]["etd"]

            #3.计算dtime,并求和
            sum_dtime += Timetable.loc[i]["atd"] - Timetable.loc[i]["etd"]

        print(sum_dtime)
        #对航班的sum_dtime的处理
        for i in range(iteration_num):
            fcfs_record.append(sum_dtime)

        return fcfs_record